package com.google.code.meitt.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;

import com.google.code.meitt.database.DB;
import com.google.code.meitt.model.Game;
import com.google.code.meitt.model.InitGame;
import com.google.gson.Gson;

public class LobbyServlet extends HttpServlet {

	public static final String GAME_INIT = "gameInit";
	private static final long serialVersionUID = 1L;
	private static final Gson gson = new Gson();

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		resp.setContentType("application/json");
		PrintWriter out = resp.getWriter();
		out.write(gson.toJson(getGames()));
	}

	private List<Game> getGames() {
		List<Map<String, Object>> result = DB
				.runQuery("select g.id,p.name from games g inner join players p on p.id=g.creator where g.joiner is null");
		List<Game> games = new ArrayList<Game>();
		for (Map<String, Object> map : result) {
			games.add(new Game("game-" + map.get("id"), map.get("name")
					+ "'s game", "waiting"));
		}

		return games;
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		resp.setContentType("application/json");
		InitGame initGame = gson.fromJson(req.getParameter("data"),
				InitGame.class);
		String outcome = "failure";
		if (StringUtils.isBlank(initGame.getGameId())) {
			outcome = createNewGame(initGame.getUserName());
			initGame.setGameId(outcome);
		} else if (isGameOpen(initGame.getGameIdInt())) {
			outcome = joinGame(initGame);
		}
		if (!outcome.equals("failure")) {
			HttpSession session = req.getSession();
			session.setAttribute(GAME_INIT, initGame);
		}
		PrintWriter out = resp.getWriter();
		out.write("{\"outcome\":\"" + outcome + "\"}");
	}

	private String joinGame(InitGame game) {
		int userId = getOrCreateUser(game.getUserName());
		boolean result = DB.runUpdate("update games set joiner=" + userId
				+ " where id=" + game.getGameIdInt());
		return result ? "success" : "failure";
	}

	private boolean isGameOpen(Integer gameId) {
		List<Map<String, Object>> result = DB
				.runQuery("select joiner from games where id=" + gameId);
		if (!result.isEmpty() && result.get(0).get("joiner") == null) {
			return true;
		}
		return false;
	}

	private String createNewGame(String user) {
		int userId = getOrCreateUser(user);
		return ""
				+ DB.runInsert("insert into games (creator) values ('" + userId
						+ "')");
	}

	private int getOrCreateUser(String user) {
		List<Map<String, Object>> result = DB
				.runQuery("select * from players where name='" + user + "'");
		int userId = 0;
		if (!result.isEmpty()) {
			userId = (Integer) result.get(0).get("id");
		}
		if (userId == 0) {
			userId = DB.runInsert("insert into players (name) values ('" + user
					+ "')");
		}
		return userId;
	}

}
